#pragma once

#include "Widgets/Widget.h"
#include "Widgets/Dock/DockWidgetTitleBarParent.h"
#include "DockWidgetTitleBarBase.h"
#include "Widgets/RectangleWidget.h"
#include "Widgets/Mouse/MouseWidget.h"


#include "DockLayout.m.h"

class RDockWidgetTitleBar;

RENUM()
enum class EDockLayoutDirection
{
    //all dcocked widgets are stacked
    //and must be RDockWidgetPtr
    // support 0 docked widget at lowest
    Stacked, 
    
    //only have two dockable widgets at most
    //, first is left, second is right,
    //if only one, the right side is blank
    //must have at least one dockable widget
    Horizontal, 
    
    //only have two dockable widgets at most
    //, first is up, second is down,
    //if only one, the down side is blank
    //must have at least one dockable widget
    Vertical
};

//dock layout is a widget that 
//allow user dock a normal Widget or another RDockLayout to it
//horizontal and vertival direction layout will auto convert to stacked layout
//when docked widget num <2;
RCLASS()
class WHENGINE_API RDockLayout: public RWidget
{
    ROBJECT
public:
    RDockLayout();


    
    //width of spliter, in pixel
    float SpliterWidth= 4.f; 

    void SetDirection(EDockLayoutDirection InDirection);

    EDockLayoutDirection GetDirection();
    
    //dock a widget to this layout
    //will auto create widget by RegisteredWidgetName
    void DockWidget(const CString& InRegisteredWidgetName,float SizeWeight=1.f);


    void DockLayout(RDockLayoutPtr InAnotherDockWidget,float SizeWeight=1.f);

    void Undock(RWidgetPtr InDockWidget);

    TVector<RWidgetPtr> GetDockedWidgetsAndLayouts();
    int32_t GetDockedWidgetsAndLayoutsNum();
    RWidgetPtr GetDockedWidgetsOrLayout(int32_t InIndex);
    float GetSizeWeight(int32_t InIndex);
    //return empty if InIndex point to a layout
    CString GetDockedWidgetName(int32_t InIndex);
    bool HasDockedWidget(CString InRegisteredWidgetName);

    //select a docked widget in stacked layout
    void SetSelectedWidgetInStack(const CString& InRegisteredWidgetName);
    void SetSelectedIndexInStack(int32_t InIndex);
    int32_t GetSelectedIndexInStack();

    //if true, close the window when last docked widget removed
    //default is false;
    //designed for auto generated window and dock layout
    void SetCloseWindowWhenLastDockedWidgetRemoved(bool InValue);

    void SetGroupName(const CString& InGroupName);

    const CString& GetGroupName();

    float TitleBarHeight=25.f;
    //title bar class, must implement ITitleBar
    TSubclassOf<RDockWidgetTitleBarBase> TitleBarClass;
    
    
protected:
    EDockLayoutDirection Direction = EDockLayoutDirection::Stacked;
    //depends docked widget size, default weight is 1 
    //TVector<float> SizeWeights; 

    struct SDockedWidget
    {
        SDockedWidget()=default;

        SDockedWidget(RDockLayoutPtr InLayout,float InSizeWeight)
        {
            Widget=InLayout;
            SizeWeight=InSizeWeight;
        }

        SDockedWidget(RWidgetPtr InWidget,const CString& InWidgetName , RDockWidgetTitleBarParentPtr InTitle,float InSizeWeight )
        {
            Widget=InWidget;
            WidgetName=InWidgetName;
            Title=InTitle;
            SizeWeight=InSizeWeight;
        }


        RWidgetPtr Widget; // might be layout 

        CString WidgetName; //only valid when Widget is layout

        RDockWidgetTitleBarParentPtr Title; // only valid when Widget is not layout

        float SizeWeight=1.f;
    };

    //all docked widgets
    //first is left/up side, second is right/down side
    //if docked widget is RDockLayout, do not have TitleBar
    TVector<SDockedWidget> DockedWidgets;
    
    //which docked widget is selected in stacked layout
    //is == -1 , auto select the first docked widget
    //only valid for stacked layout
    int32_t SelectedIndexInStack=-1;

    //if true, close the window when last docked widget removed
    bool bCloseWindowWhenLastDockedWidgetRemoved = false;

    CString LayoutGroupName=U"Default";


    //last frame widget positions
    TVector<float> WidgetPositions;

    //last frame widget sizes
    TVector<float> WidgetSizes;



    RRectangleWidgetWeakPtr Background;

    TVector<RRectangleWidgetWeakPtr> Spliters;
    TVector<RMouseWidgetWeakPtr> SpliterMouses;

    void DockWidget(const SDockedWidget& InDockedWidget,bool bToFirst=false);

    virtual void CalculateChildrenPresentPositionAndSize() override;
    virtual void PaintSubWidgets(uint16_t& InZOrder) override;

    void OnDockWidgetTitleBarCloseClicked(RDockWidgetTitleBarParentPtr InTitleBar);
    
    //return the docked widget 
    RDockLayout::SDockedWidget RemoveDockedWidget(RDockWidgetTitleBarParentPtr InTitleBar);

    //move docked widget to parent layout
    void MergeToParentLayout();

    void SameDirectionMergeToParentLayout();

    static void MoveDockedWidgets(
        RDockLayoutPtr InFromLayout
        ,RDockLayoutPtr InToLayout
        ,bool CopyDirectionAndPercent = false
        );

    //only valid for draging title bar
    //is background  title bars when try to insert title bar into exist title bars 
    TVector<RDockWidgetTitleBarParentWeakPtr> ExtraTitleBars;
    int32_t DragingTitleBarIndex=-1;
    bool bIsOverridingTitleBar = false;


};